package nwsimplex.graph;

/**
 *
 * @author mfj
 */
public class Edge {

    /**
     * the current flow of this edge
     */
    public int flow;
    /**
     * the cost of this edge
     */
    public final int cost;
    /**
     * the lower capacity of this edge
     */
    public final int lowerCapacity;
    /**
     * the upper capacity of this edge
     */
    public final int upperCapacity;
    /**
     * the vertiex from which this edge goes out
     */
    public final Vertex from;
    /**
     * the vertex from which this edge goes in
     */
    public final Vertex to;

    /**
     *
     * @param flow
     * @param cost
     * @param lowerCapacity
     * @param upperCapacity
     * @param from
     * @param to
     */
    public Edge(int flow, int cost, int lowerCapacity, int upperCapacity, Vertex from, Vertex to) {
        this.flow = flow;
        this.cost = cost;
        this.lowerCapacity = lowerCapacity;
        this.upperCapacity = upperCapacity;
        this.from = from;
        this.to = to;
    }

    /**
     * Indicates that the edge flow reaches the lower bound
     *
     * @return {@code flow == lowerCapacity}
     */
    public boolean hasLowerBound() {
        return flow == lowerCapacity;
    }

    /**
     * Indicates that the edge flow reaches the upper bound
     *
     * @return {@code flow == capacity}
     */
    public boolean hasUpperBound() {
        return flow == upperCapacity;
    }

    /**
     * Gets the reduced costs.
     *
     * @return {@code cost - from.potential + to.potential}
     */
    public int reducedCost() {
        return cost - from.potential + to.potential;
    }

    public void moderatePotentials(Vertex changed, int change) {
        // red cost = cost - from.potential + to.potential
        if (changed == to) {
            from.potential += change;
        } else {
            to.potential -= change;
        }
    }

    /**
     * Tests if the specified edge is downward pointing within the spanningtree
     * meaning that the origin is closer to the root then the target vertex.
     * Note that this ist not the case if this edge is not contained within this
     * spanning tree.
     *
     * @return {@code e.from == e.to.parent}
     */
    public boolean isDownwardPointing() {
        return from == to.parent;
    }

    /**
     * Tests if the specified edge is upward pointing within the spanningtree
     * meaning that the target vertex is closer to the root then the origin.
     * Note that this ist not the case if this edge is not contained within this
     * spanning tree.
     *
     * @return {@code e.to == e.from.parent}
     */
    public boolean isUpwardPointing() {
        return to == from.parent;
    }

    /**
     * Tests if this edge is contained within the tree.
     *
     * @return {@code isUpwardPointing() || isDownwardPointing()}
     */
    public boolean isTreeEdge() {
        return isUpwardPointing() || isDownwardPointing();
    }
}
